package tt.dz.appserver.service.business.imp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.avro.AvroRemoteException;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;

import tt.dz.appserver.dao.ext.AppVersionDao;
import tt.dz.appserver.dao.ext.BannerDao;
import tt.dz.appserver.dao.ext.CityDao;
import tt.dz.appserver.dao.ext.ProvinceDao;
import tt.dz.appserver.dao.ext.ServerLabelDao;
import tt.dz.appserver.dao.ext.ServiceStationDao;
import tt.dz.appserver.entity.model.AppVersion;
import tt.dz.appserver.entity.model.ResultMappingEntity;
import tt.dz.appserver.entity.model.ServiceStation;
import tt.dz.appserver.entity.model.dic.City;
import tt.dz.appserver.entity.model.dic.Province;
import tt.dz.appserver.entity.model.pub.Banner;
import tt.dz.appserver.entity.model.pub.ServerLabel;
import tt.dz.appserver.entity.vo.AppVersionVo;
import tt.dz.appserver.entity.vo.BannerVo;
import tt.dz.appserver.entity.vo.CityVo;
import tt.dz.appserver.entity.vo.JSSign;
import tt.dz.appserver.entity.vo.OperatorVO;
import tt.dz.appserver.entity.vo.ServerLabelVO;
import tt.dz.appserver.service.avro.client.main.MSRPCService;
import tt.dz.appserver.service.avro.client.oms.dzttOmsServiceProtocol;
import tt.dz.appserver.service.business.PublicService;
import tt.dz.appserver.service.business.UserInfoService;
import tt.dz.appserver.util.CodeUtils;
import tt.dz.appserver.util.Constants;
import tt.dz.appserver.util.ConverUtil;
import tt.dz.appserver.util.Result;
import tt.dz.appserver.util.StringUtils;
import tt.dz.appserver.util.WeiXinUtils;
import tt.dz.appserver.util.date.DateUtil;
import tt.dz.appserver.util.dzcode.OmsCode;
import tt.dz.appserver.util.enums.Response;
import tt.dz.appserver.util.enums.userIsExists;
import tt.dz.appserver.util.http.HttpUtils;
import tt.dz.appserver.util.json.JsonUtils;
import tt.dz.base.authentication.service.AuthenService;

/**
 * 公共业务实现
 * 
 * @author xielf
 *
 */
public class PublicServiceImpl implements PublicService {

	/** 日志 */
	private static final Logger LOG = Logger.getLogger("[公共业务]:");

	/** 主服务器访问接口 */
	@Resource(name = "mainMessageProtocolRequestor")
	private MSRPCService msrpcService;
	
	@Resource(name = "omsMessageProtocolRequestor")
	private dzttOmsServiceProtocol omsService;

	/** baseplatform 授权业务接口 */
	@Resource
	private AuthenService authService;
	/** App 版本操作 */
	@Resource
	private AppVersionDao appVersionDao;

	/** 服务点数据操作 **/
	@Resource
	private ServiceStationDao serviceStationDao;

	@Resource
	private UserInfoService userInfoService;

	/** banner图片 */
	@Resource
	private BannerDao bannerDao;
	
	@Resource
	private ServerLabelDao serverLabelDao;	
	
	@Resource
	ProvinceDao provinceDao;
	@Resource
	CityDao cityDao;

	@Override
	public JSONObject sendVerifyCode(String phone, String merchantCode) throws AvroRemoteException {

		JSONObject resultJsonObject = null;
		// 拼装参数
		Map<String, String> params = new HashMap<String, String>();
		params.put("mobileNo", phone);
		params.put("merchantCode", merchantCode);
		// 发送验证码
		String resultJsonString = msrpcService.getCheckCode(JSON.toJSONString(params)).toString();

		LOG.info("MS发送验证码返回:" + resultJsonString);

		JSONObject mainServerResult = JSONObject.parseObject(resultJsonString);

		// 操作结果
		int opResult = mainServerResult.getInteger(Constants.MainServerResultField.OP_RESULT);
		if (opResult == 1) {
			resultJsonObject = JsonUtils.getSuccessJson();
			resultJsonObject.put("checkCode", mainServerResult.getString("checkCode"));
		} else {
			String errorCode = mainServerResult.getString(Constants.MainServerResultField.ERROR_CODE);
			Response response = CodeUtils.getCodeByMainServerCode(errorCode);
			resultJsonObject = JsonUtils.getFailJson(response);
		}
		return resultJsonObject;
	}

	//TODO 该方法代码结构需要调整
	@Override
	public JSONObject validationVerifyCode(String phone, String verifyCode, String source, String merchantCode,
			String account,String type,String bindingType) throws AvroRemoteException {
		LOG.info("传入参数source="+source+"merchantCode="+merchantCode+"account="+account+"");
		JSONObject resultJsonObject = new JSONObject();
		// 拼装参数
		Map<String, String> params = new HashMap<String, String>();
		params.put("mobileNo", phone);
		params.put("checkCode", verifyCode);
		// 发送验证码
		String resultJsonString = msrpcService.verifyCheckCode(JSON.toJSONString(params)).toString();

		LOG.info("MS验证码校验返回:" + resultJsonString);

		JSONObject mainServerResult = JSONObject.parseObject(resultJsonString);

		// 验证码返回结果 1 成功
		int opResult = mainServerResult.getInteger(Constants.MainServerResultField.OP_RESULT);
		
		if (opResult != 1) {
			String errorCode = mainServerResult.getString(Constants.MainServerResultField.ERROR_CODE);
			Response response = CodeUtils.getCodeByMainServerCode(errorCode);
			return  resultJsonObject = JsonUtils.getFailJson(response);
		}

		// resultJsonObject=JsonUtils.getSuccessJson();
		// 验证码返回成功，且访问为华体微信根据运营商编码+手机号+华体是否存在判断用户是否绑定
		LOG.info("消息渠道【"+source+"】运营商编码【"+merchantCode+"】");
		//XXX 当前这么写是因为华体微信绑定没有传type, 代码合理性需要穿；导致同属于微信绑定与电桩app快捷登录验证码，找回密码验证码区分困难
			if ((ConverUtil.checkDataSource(source, merchantCode)==1||
					(ConverUtil.checkDataSource(source, merchantCode)==2&&type.equals("1")))
					&& account != "") {
			
			// 验证用户存在
			resultJsonString = userIsExist(phone, merchantCode, source);
			mainServerResult = JSONObject.parseObject(resultJsonString);
			opResult = mainServerResult.getInteger(Constants.MainServerResultField.OP_RESULT);
			String isExists = mainServerResult.getString("isExists");
			LOG.info("验证用户是否存在返回结果："+resultJsonString);
			// 用户存在
			if (opResult == 1 && userIsExists.YES.getCode().equals(isExists)) {

				// 绑定第三方用户
				resultJsonString = bindThirdAccount(phone, source, account, merchantCode,bindingType);
				mainServerResult = JSONObject.parseObject(resultJsonString);
				LOG.info("验证用户绑定返回结果："+resultJsonString);
				opResult = mainServerResult.getInteger(Constants.MainServerResultField.OP_RESULT);
				// 绑定成功，调用登录接口
				if (opResult == 1) {
					resultJsonObject = JsonUtils.getSuccessJson();
				} else {
					String errorCode = mainServerResult.getString(Constants.MainServerResultField.ERROR_CODE);
					Response response = CodeUtils.getCodeByMainServerCode(errorCode);
					resultJsonObject = JsonUtils.getFailJson(response);
				}

			} else if (opResult == 1 && userIsExists.NO.getCode().equals(isExists)) {
				// 用户不存在
				// 调用注册接口
				mainServerResult = userInfoService.register(phone, source, merchantCode, verifyCode);
				LOG.info("注册存在返回结果："+resultJsonString);
				// 注册成功，调用绑定接口
				if (mainServerResult.getString("code").equals(Response.SUCCESS.getCode())) {
					// 绑定第三方用户
					resultJsonString = bindThirdAccount(phone, source, account, merchantCode,bindingType);
					mainServerResult = JSONObject.parseObject(resultJsonString);
					opResult = mainServerResult.getInteger(Constants.MainServerResultField.OP_RESULT);
					// 绑定成功，调用登录接口
					LOG.info("用户绑定结果：" + resultJsonString);
					if (opResult == 1) {
						return resultJsonObject = JsonUtils.getSuccessJson();
					} else {
						// 绑定失败
							
						String errorCode = mainServerResult.getString(Constants.MainServerResultField.ERROR_CODE);
						Response response = CodeUtils.getCodeByMainServerCode(errorCode);
						resultJsonObject = JsonUtils.getFailJson(response);
					}
				} else {
					// 用户注册失败
					LOG.error("注册失败用户："+account);
					String errorCode = mainServerResult.getString(Constants.MainServerResultField.ERROR_CODE);
					Response response = CodeUtils.getCodeByMainServerCode(errorCode);
					resultJsonObject = JsonUtils.getFailJson(response);
				}

			} else {
				// 验证用户存在失败失败 返回			
				String errorCode = mainServerResult.getString(Constants.MainServerResultField.ERROR_CODE);
				LOG.error("验证用户存在失败失败 返回" + errorCode);
				Response response = CodeUtils.getCodeByMainServerCode(errorCode);
				resultJsonObject = JsonUtils.getFailJson(response);
			}
			//电桩绑定用户
		} else {
			// 其他渠道正常验证
			resultJsonObject = JsonUtils.getSuccessJson();
		}

		return resultJsonObject;

	}

	/**
	 * 判断用户是否存在
	 * 
	 * @param phone
	 *            手机号
	 * @param merchantCode
	 *            运营商
	 * @param source
	 *            系统码，渠道
	 * @return
	 * @throws AvroRemoteException
	 */
	private String userIsExist(String phone, String merchantCode, String source) throws AvroRemoteException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("mobileNo", phone);
		params.put("merchantCode", merchantCode);
		params.put("sysCode", source);
		return msrpcService.userIsExists(JSON.toJSONString(params)).toString();
	}

	/**
	 * 
	 * @param phone
	 *            手机号
	 * @param merchantCode
	 *            运营商
	 * @param source
	 *            系统码，渠道
	 * @param account
	 *            运营商在渠道下的帐号
	 * @return
	 * @throws AvroRemoteException
	 */
	private   String bindThirdAccount(String phone, String source, String account, String merchantCode,String bindingType)
			throws AvroRemoteException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("tokenKey", phone);
		params.put("thirdUuuid", account);
		params.put("merchantCode", merchantCode);
		params.put("sysCode", source);
		if (ConverUtil.checkDataSource(source, merchantCode)==1||ConverUtil.checkDataSource(source, merchantCode)==2) {
			if(bindingType.equals("")){
				bindingType="1";
			}
			params.put("bindType", bindingType);
		} else {
			// 如果没有匹配上，绑定失败
			LOG.error("系统编码=" + source + "错误");
			JSONObject resultJsonObject = new JSONObject();
			resultJsonObject.put("isSuccess", 0);
			resultJsonObject.put("errorMsg", "系统编号错误");
			resultJsonObject.put("errorCode", "");
			return resultJsonObject.toJSONString();
		}
		return msrpcService.bindThirdAccount(JSON.toJSONString(params)).toString();
	}

	@Override
	public ResultMappingEntity getLatestAppVersion(Integer osType) {

		AppVersion appVersion = appVersionDao.findAppLatestVersionByOsType(osType);
		if (appVersion != null) {
			AppVersionVo appVersionVo = new AppVersionVo();
			appVersionVo.setRemark(appVersion.getDescription());
			appVersionVo.setDownloadUrl(appVersion.getDownload_url());
			appVersionVo.setOsType(appVersion.getOs_type().toString());
			appVersionVo.setReleaseTime(DateUtil.getDateTime(appVersion.getRelease_time()));
			appVersionVo.setVersionCode(appVersion.getVersion_code());
			appVersionVo.setSupportOsVersion(appVersion.getSupport_os_version().toString());

			ResultMappingEntity resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
					Response.SUCCESS.getMsg(), appVersionVo);
			return resultMappingEntity;
		}
		return null;
	}

	@Override
	public ResultMappingEntity getServiceStation(int serviceType, int pageNo, float longitude, float latitude) {

		List<Map<String, Object>> listMap = serviceStationDao.findNearServiceStationValid(serviceType, pageNo,
				longitude, latitude);

		ResultMappingEntity resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
				Response.SUCCESS.getMsg(), listMap);
		return resultMappingEntity;
	}

	@Override
	public ResultMappingEntity getServiceStation(String serviceStationId) {

		ServiceStation serviceStation = serviceStationDao.findServiceStationByServiceStationId(serviceStationId);

		ResultMappingEntity resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
				Response.SUCCESS.getMsg(), serviceStation);
		return resultMappingEntity;
	}

	@Override
	public ResultMappingEntity getAllBannerList() {

		List<Banner> banners = bannerDao.findAllBannerList();

		List<BannerVo> bannerVos = new ArrayList<>();

		for (Banner banner : banners) {
			BannerVo bannerVo = new BannerVo();
			bannerVo.setBannerId(banner.getBanner_id());
			bannerVo.setBannerType(banner.getBanner_type());
			bannerVo.setUrl(banner.getUrl());
			bannerVos.add(bannerVo);
		}

		ResultMappingEntity resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
				Response.SUCCESS.getMsg(), bannerVos);
		return resultMappingEntity;
	}

	@Override
	public ResultMappingEntity getAccessToken(String resoure, String merchantCode,String code) {
			
		LOG.info("访问凭证接口获取运营商【"+resoure+"】,运营商编码【"+merchantCode+"】系统码code【"+code+"】");
		JSONObject  accessToken=  WeiXinUtils.getAccountAccessToken(resoure, merchantCode,code);
		String errorCode = accessToken.getString(Constants.MainServerResultField.ERROR_CODE);
		LOG.info("微信返回的数据【"+JSON.toJSONString(accessToken)+"");
		ResultMappingEntity   resultMappingEntity=null;

		if(errorCode==null){
			 resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
						Response.SUCCESS.getMsg(),accessToken);			 
		}else{
			resultMappingEntity = Result.responseBody("0",
					"参数错误",accessToken);
		}
		return resultMappingEntity;
	}
	
	@Override
	public ResultMappingEntity getThirdUserinfo(String access_token, String openid,String lang) {
			
		LOG.info("访问凭证接口获取传入token【"+access_token+"】,用户openid【"+openid+"】语言版本【"+lang+"】");
		
		JSONObject   validToken =WeiXinUtils.validToken(access_token, openid);
			
		LOG.info("微信用户验证token是否有效返回的数据【"+JSON.toJSONString(validToken)+"】");
		String errorCode = validToken.getString(Constants.MainServerResultField.ERROR_CODE);
		ResultMappingEntity   resultMappingEntity=null;
		if(!errorCode.equals("0")){
			 resultMappingEntity = Result.responseBody("0",
						"参数错误",validToken);
			 return resultMappingEntity;
		}
		
		JSONObject  accessToken=  WeiXinUtils.getTridUserinfo(access_token, openid,lang);
		 errorCode = accessToken.getString(Constants.MainServerResultField.ERROR_CODE);
		LOG.info("微信用户详情返回的数据【"+JSON.toJSONString(accessToken)+"】");
		
		//TODO 定义微信错误码
		if(errorCode.equals("40003")){
			 resultMappingEntity = Result.responseBody("0",
					"参数错误",accessToken);
		}else{
			 resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
					Response.SUCCESS.getMsg(),accessToken);
		}
		return resultMappingEntity;
	}
	@Override
	public ResultMappingEntity getJsSign(String source, String merchantCode, String signType, String url) {
			
		LOG.info("访问凭证接口获取运营商【"+source+"】,运营商编码【"+merchantCode+"】签名类型signType【"+signType+"】签名的url【"+url+"】");
		JSSign  accessToken=  WeiXinUtils.getJsSign(source, merchantCode, signType, url);
		
		ResultMappingEntity   resultMappingEntity=null;
		//TODO 定义微信错误码
		if(accessToken!=null){
			 resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
						Response.SUCCESS.getMsg(),accessToken);			 
		}else{
			resultMappingEntity = Result.responseBody("0",
					"参数错误",accessToken);
		}
		return resultMappingEntity;
	}

	@Override
	public ResultMappingEntity getLables(Integer type,Integer level ) {
		LOG.info("查询标签的类型:【"+type+"】");
		
		ResultMappingEntity   resultMappingEntity = null;
		
		ServerLabel label= new ServerLabel();
		label.setLabel_type(type);
		label.setLevel(level);
			
		 List<ServerLabel> lables=serverLabelDao.findLabel(label);
		 List<ServerLabelVO> lalesVos=Lists.newArrayList();
		 	for(ServerLabel lable:lables){
		 		ServerLabelVO lableVo=new ServerLabelVO();
		 		lableVo.setLabelId(lable.getLabel_id());
		 		lableVo.setLabelName(lable.getLabel_name());
		 		lableVo.setType(lable.getLabel_type());
		 		lableVo.setLevel(lable.getLevel());
		 		lalesVos.add(lableVo);
		 		
		 	}
			 resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
						Response.SUCCESS.getMsg(),lalesVos);			 
		
		
		return resultMappingEntity;
	}

	@Override
	public ResultMappingEntity getCityNameAndCodeByCoordinate(String  longtitude, String latitude)throws AvroRemoteException {
		
		LOG.info("查询地点的坐标纬度【"+latitude+"】"+"经度【"+longtitude+"】");
		
		ResultMappingEntity   resultMappingEntity = null;
		CityVo  cityVo= new CityVo();
		Map<String, String> paramMap= new HashMap<String, String>(); 
		paramMap.put("location",  latitude+","+longtitude);
		paramMap.put("output", "json");
		paramMap.put("key", Constants.baiduMapKey);
		
		//访问百度api获取改经纬度的城市名称
		String reslutString = HttpUtils.getRequest(Constants.publicUrl.BAIDUMAP_GEOCODER, paramMap);
		LOG.info(reslutString);
		JSONObject reslut = JSON.parseObject(reslutString);
		String status = reslut.getString("status");
		if(status.equals("OK")){
			JSONObject  resultStr=reslut.getJSONObject("result");
			if(resultStr!=null){
				JSONObject addressComponent = resultStr.getJSONObject("addressComponent");
				if(addressComponent != null){				
					String cityName = addressComponent.getString("city");
					String provinceName = addressComponent.getString("province");
					cityVo.setCityName(cityName);
					cityVo.setProvinceName(provinceName);
					String provinceId=null;
					if(StringUtils.isNotBlank(provinceName)){
						List<Province>  provinces = provinceDao.findProvince(provinceName);
						if(provinces != null && provinces.size() == 1){
							provinceId=provinces.get(0).getProvince_id();
							cityVo.setProvinceId(provinceId);
						}
					}
					
					List<City> citys = cityDao.findCityByProvince(provinceId, cityName);
					if(citys != null && citys.size() == 1){
						cityVo.setCityId(citys.get(0).getCity_id());
					}
				}
			}						
		}
		
		 resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
					Response.SUCCESS.getMsg(),cityVo);
		 
		return resultMappingEntity;
	}

	@Override
	public ResultMappingEntity getAllOperator() throws AvroRemoteException {
		
		ResultMappingEntity   resultMappingEntity = null;
		String omsString = omsService.getAllOperator().toString();
		
		// json转换
		JSONObject chargerResultObject = JSONObject.parseObject(omsString);
		// 获取操作结果
		String code = chargerResultObject.getString(Constants.OmsServerResultField.CODE);
		LOG.info("获取所有运营商详细接口,OMS返回:" + omsString);

		// 操作成功
		if (OmsCode.SUCCESS.equals(code)) {
			JSONObject operatorJson = chargerResultObject.getJSONObject("pojo");
			OperatorVO  operatorVo = JsonUtils.JsonToObjectOfClass(operatorJson, OperatorVO.class);
			
			resultMappingEntity = Result.responseBody(Response.SUCCESS.getCode(),
					Response.SUCCESS.getMsg(),operatorVo);
			
		}else{
			resultMappingEntity = Result.responseBody(Response.FIAL.getCode(),
					Response.FIAL.getMsg());
			
		}
		return resultMappingEntity;
	}

}
